package org.ithang.concurrent;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

//如何自己实现线程同步？原理是“自旋”
public class SelfSync {

	private static AtomicInteger lock=new AtomicInteger(0); 
	
	
	public static void demo(){
		while(!lock.compareAndSet(0, 1)){//如果lock的值为0，则设置lock的值为1，否则不做处理
			try{
		        Thread.currentThread().wait();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		
		System.out.println("demo="+Thread.currentThread().getName());
		try{
		    Thread.sleep(5000);//业务逻辑执行时间
		}catch(Exception e){
			
		}finally {
			lock.set(0);
			Thread.currentThread().notifyAll();
		}
	}
	
	
	//自旋
	public static void demoA(){
		
		while(!lock.compareAndSet(0, 1)){//如果lock的值为0，则设置lock的值为1，否则不做处理
		    ////缺点:这里白白浪费CPU资源
		}
		
		System.out.println("demo="+Thread.currentThread().getName());
		try{
		    Thread.sleep(5000);//业务逻辑执行时间
		}catch(Exception e){
			
		}finally {
			lock.set(0);
		}
	}
	
	//yield+自旋
	public static void demoB(){
		while(!lock.compareAndSet(0, 1)){//如果lock的值为0，则设置lock的值为1，否则不做处理
	    	//当前线程让出CPU资源
			Thread.yield();
			//缺点:如果10个线程在跑，其中只有一个拿着锁，虽然其它线程让出了CPU资源，但不一定会让给拿着锁的线程，还会有一定程度的浪费CPU
		}
		
		System.out.println("demo="+Thread.currentThread().getName());
		try{
		    Thread.sleep(5000);//业务逻辑执行时间
		}catch(Exception e){
			
		}finally {
			lock.set(0);
		}
	}
	
	//sleep+自旋
	public static void demoC(){
		while(!lock.compareAndSet(0, 1)){//如果lock的值为0，则设置lock的值为1，否则不做处理
	    	//当前线程睡眠，让出CPU资源
			try{
			    Thread.sleep(1000);
			}catch(Exception e){
				
			}
			//缺点:睡觉时间很难确定，大于或小于 业务逻辑执行时，都很会出现浪费CPU的情况
		}
		
		System.out.println("demo="+Thread.currentThread().getName());
		try{
		    Thread.sleep(5000);//业务逻辑执行时间
		}catch(Exception e){
			
		}finally {
			lock.set(0);
		}
	}
	
	//先进先出
	private static Queue<Thread> queue = new LinkedList<>();
	//park+自旋
	public static void demoD(){
		while(!lock.compareAndSet(0, 1)){//如果lock的值为0，则设置lock的值为1，否则不做处理
	    	//把当前线程放入队列，并即时睡眠，让出CPU
			queue.add(Thread.currentThread());
			LockSupport.park();
			//缺点:
		}
		
		System.out.println("demo="+Thread.currentThread().getName());
		try{
		    Thread.sleep(5000);//业务逻辑执行时间
		}catch(Exception e){
			
		}finally {
			lock.set(0);
			LockSupport.unpark(queue.poll());//即时唤醒
			//poll 得到队列中第一个对象，并从队列中移除
		}
	}
	
	
}
